#include "stdafx.h"

#include "ClassicBusiness.h"
#include "Business/Policy/ClassicBusinessContext.h"
#include "Business/Command.h"
#include "Business/BollingerCalculator.h"
#include "Utils/FastBlockQueue.h"
#include "Business/QueueContext.h"
#include "Business/Command.h"

ClassicBusiness::ClassicBusiness(Customer& customer,ClassicBusinessArgument const& argument,
								 BollingerCalculatorManager& bollingerManager,
								 MarketStorage const& marketStorage,
								 QueueContext& queueContext, 
								 DealingRepository& dealingRepository,
								 CancellationRepository& cancellationRepository)
:AutoUpdateUIBusiness(customer),m_bollingerManager(bollingerManager),m_queueContext(queueContext),
m_dealingRepository(dealingRepository),m_cancellationRepository(cancellationRepository),m_bollingers(NULL)
{
	m_context.reset(new ClassicBusinessContext(customer,*this,argument,marketStorage,queueContext,dealingRepository,cancellationRepository));
	AddContract(argument.GetMajor());
	AddContract(argument.GetMinor());
}

void ClassicBusiness::DoOnMarket(Market const& market)
{
	m_context->OnMarket(market);
	UpdateUI(GetSnapshot());
}

void ClassicBusiness::DoOnDealing(Dealing const& dealing)
{
	AutoSnapshotNotifier notifier(*this);
	m_context->OnDealing(dealing);
}

void ClassicBusiness::DoOnTimeout(RequestTimeout const& requestTimeout)
{
	AutoSnapshotNotifier notifier(*this);
	m_context->OnTimeout(requestTimeout);
}

void ClassicBusiness::DoOnTrade(Trade const& trade)
{
	AutoSnapshotNotifier notifier(*this);
	m_context->OnTrade(trade);
}

void ClassicBusiness::DoOnCommand(Command const& command)
{
	AutoSnapshotNotifier notifier(*this);
	switch (command.type)
	{
	case Command::CLEAR_COMMAND:
		{
			//m_context->Clear();
		}
		break;
	case Command::STOP_COMMAND:
		{
			m_context->Stop();
		}
		break;
	case Command::START_COMMAND:
		{
			m_context->Start();
		}
		break;
	case Command::EDIT_COMMAND:
		{
			m_context->Edit();
		}
		break;
	case Command::UPDATE_ARGUMENT_COMMAND:
		{
			ClassicBusinessArgument& argument = *(ClassicBusinessArgument*)command.data;
			UpdateArgument(argument);
		}
		break;
	}
}

ClassicBusinessArgument const& ClassicBusiness::GetArgument() const
{
	return m_context->GetArgument();
}

void ClassicBusiness::DoOnInit()
{
	BollingerParameter parameter(m_context->GetArgument().GetContracts(),600,30,1.96);
	BollingerCalculater& bollingerCalculater = m_bollingerManager.Add(parameter);
	m_context->SetBollingers(&bollingerCalculater.GetBollingers());
}

void ClassicBusiness::UpdateArgument(ClassicBusinessArgument &argument)
{
	switch (argument.GetType())
	{
	case ClassicBusinessArgument::AUTO:
		m_context->UpdateBalance(argument.GetOpenBalance(),argument.GetProfitBalance());
		break;
	case ClassicBusinessArgument::BOTH:
	case ClassicBusinessArgument::JUST_BEARISH:
	case ClassicBusinessArgument::JUST_BULLISH:
		m_context->UpdateBand(argument.GetBearish(),argument.GetBullish());
		break;
	default:
		break;
	}
}

bool ClassicBusiness::IsEditStatus() const
{
	return m_context->IsEditable();
}

void ClassicBusiness::DoOnExchangeStatus(int exchangeStatus)
{
	UNREFERENCED_PARAMETER(exchangeStatus);
}

ClassicBusinessSnapshot ClassicBusiness::GetSnapshot() const
{
	ClassicBusinessSnapshot snapshot = {0};
	snapshot.statusName = m_context->GetCurrentStatusName();
	ArbitrageLegs const* pLegs = m_context->GetCurrrentLegsPointer();
	if (pLegs)
	{
		snapshot.minorDirection = pLegs->GetMinorOpenLeg().GetDirection();
	}
	else
	{
		snapshot.minorDirection = -1;
	}
	snapshot.majorPosition = m_context->GetPosition().GetMajor().GetQuantity();
	snapshot.minorPosition = m_context->GetPosition().GetMinor().GetQuantity();
	snapshot.profit = m_context->GetProfit();
	return snapshot;
}


void ClassicBusiness::UpdateUI(ClassicBusinessSnapshot const& snapshot)
{
	QueueItem item = {0};
	item.type = QueueItem::COMMAND;
	Command& cmd = *(Command*)item.data;
	cmd.type = Command::UI_UPDATE_BUSINESS_INFO;
	cmd.business = this;
	ClassicBusinessSnapshot& cmdSnapshot = *(ClassicBusinessSnapshot*)cmd.data;
	cmdSnapshot = snapshot;
	m_queueContext.GetUIQueue().Push(item);
}

void ClassicBusiness::DoOnPendingMarket(PendingMarket const&)
{
}